home *** CD-ROM | disk | FTP | other *** search
/ Fritz: All Fritz / All Fritz.zip / All Fritz / FILES / PROGNG_C / TPTC17GS.LZH / TPCSTMT.INC < prev    next >
Text File  |  1988-05-03  |  22KB  |  1,048 lines

  1.  
  2.  
  3. (*
  4.  * TPTC - Turbo Pascal to C translator
  5.  *
  6.  * (C) 1988 Samuel H. Smith (rev. 13-Feb-88)
  7.  *
  8.  *)
  9.  
  10. (********************************************************************)
  11. (*
  12.  * control statement processors
  13.  *    for, while, repeat, with, idents
  14.  *
  15.  * all expect tok to be keyword
  16.  * all exit at end of statement with ltok as ; or end
  17.  *
  18.  *)
  19.  
  20. procedure pfor;
  21. var
  22.    up:       boolean;
  23.    id:       string80;
  24.    low,high: string80;
  25.  
  26. begin
  27.    if debug_parse then write(' <for>');
  28.  
  29.    nospace := true;
  30.    puts('for (');
  31.    gettok;   {consume the FOR}
  32.  
  33.    id := plvalue;
  34.    gettok;   {consume the :=}
  35.  
  36.    low := pexpr;
  37.  
  38.    if tok = 'TO' then
  39.       up := true
  40.    else
  41.  
  42.    if tok = 'DOWNTO' then
  43.       up := false;
  44.  
  45.    gettok;
  46.    high := pexpr;
  47.  
  48.    if up then
  49.       puts(id+' = '+low+'; '+id+' <= '+high+'; '+id+'++) ')
  50.    else
  51.       puts(id+' = '+low+'; '+id+' >= '+high+'; '+id+'--) ');
  52.  
  53.    nospace := false;
  54.    gettok;   {consume the DO}
  55.    pstatement;
  56. end;
  57.  
  58.  
  59. (********************************************************************)
  60. procedure pwhile;
  61. begin
  62.    if debug_parse then write(' <while>');
  63.  
  64.    gettok;   {consume the WHILE}
  65.  
  66.    nospace := true;
  67.    puts('while ('+pexpr+') ');
  68.    nospace := false;
  69.  
  70.    gettok;   {consume the DO}
  71.    pstatement;
  72. end;
  73.  
  74.  
  75. (********************************************************************)
  76. procedure pwith;
  77. var
  78.    expr:    string;
  79.    exty:    string;
  80.    levels:  integer;
  81.  
  82. begin
  83.    if debug_parse then write(' <with>');
  84.  
  85.    gettok;   {consume the WITH}
  86.  
  87.    levels := 0;
  88.    puts('{ ');
  89.    nospace := true;
  90.       
  91.    repeat
  92.       if tok[1] = ',' then 
  93.       begin
  94.          gettok;
  95.          newline;
  96.          puts('  ');
  97.       end;
  98.          
  99.       expr := plvalue;
  100.       exty := exprtype_id;
  101.       make_pointer(expr);
  102.       
  103.       inc(levels);
  104.       inc(withlevel);
  105.       withtable[withlevel] := exty;
  106.  
  107.       puts(ljust(exty+' *',identlen));
  108.       puts('with'+itoa(withlevel)+' = '+expr+'; ');
  109.       
  110.    until tok[1] <> ',';
  111.    
  112.    nospace := false;
  113.    gettok;   {consume the DO}
  114.    
  115.    if tok[1] <> '{' then
  116.    begin
  117.       pstatement;
  118.       psemi;
  119.    end
  120.    else
  121.  
  122.    begin
  123.       gettok;                 {consume the open brace}
  124.    
  125.       while (tok[1] <> '}') and not recovery do
  126.       begin
  127.          pstatement;          {process the statement}
  128.          psemi;
  129.       end;
  130.       
  131.       gettok;                 {consume the close brace}
  132.    end;
  133.  
  134.    puts('   } ');
  135.    newline;
  136.    usesemi;
  137.  
  138.    dec(withlevel,levels);
  139. end;
  140.  
  141.  
  142. (********************************************************************)
  143. procedure prepeat;
  144. begin
  145.    if debug_parse then write(' <repeat>');
  146.  
  147.    puts('do { ');
  148.    gettok;
  149.  
  150.    while (tok <> 'UNTIL') and not recovery do
  151.    begin
  152.       pstatement;
  153.       psemi;
  154.    end;
  155.  
  156.    gettok;
  157.    nospace := true;
  158.    puts('}  while (!('+ pexpr+ '))');
  159.    nospace := false;
  160. end;
  161.  
  162.  
  163. (********************************************************************)
  164. procedure pcase;
  165. var
  166.    ex:  string80;
  167.    ex2: string80;   
  168.    i:   integer;
  169.    c:   char;
  170.  
  171. begin
  172.    if debug_parse then write(' <case>');
  173.  
  174.    gettok;
  175.    ex := pexpr;
  176.    puts('switch ('+ex+') {');
  177.  
  178.    gettok;   {consume the OF}
  179.  
  180.    while (tok[1] <> '}') and (tok <> 'ELSE') and not recovery do
  181.    begin
  182.  
  183.       repeat
  184.          if tok[1] = ',' then
  185.             gettok;
  186.  
  187.          if tok = '..' then
  188.          begin
  189.             gettok;
  190.             ex2 := pexpr;
  191.             
  192.             if (ex2[1] = '''') or (ex2[1] = '"') then
  193.                for c := succ(ex[2]) to ex2[2] do
  194.                begin
  195.                   newline;
  196.                   puts('case ''');
  197.                   case c of
  198.                      '\','''': puts('\');
  199.                   end;
  200.                   puts(c+''':   ');
  201.                end
  202.             else
  203.             
  204.             if htoi(ex2) - htoi(ex) > 128 then
  205.             begin
  206.                ltok := ex+'..'+ex2;
  207.                warning('Gigantic case range');
  208.             end 
  209.             else
  210.             
  211.             for i := succ(htoi(ex)) to htoi(ex2) do
  212.             begin
  213.                newline;
  214.                write(ofd[unitlevel],'case ',i,':   ');
  215.             end;
  216.          end
  217.          else
  218.          
  219.          begin
  220.             ex := pexpr;
  221.             newline;
  222.             puts('case '+ex+':   ');
  223.          end;
  224.  
  225.       until (tok[1] = ':') or recovery;
  226.       gettok;
  227.  
  228.       if (tok[1] <> '}') and (tok <> 'ELSE') then
  229.          pstatement;
  230.       puts('break; ');
  231.       newline;
  232.       usesemi;
  233.    end;
  234.  
  235.    if tok = 'ELSE' then
  236.    begin
  237.       newline;
  238.       puts('default: ');
  239.       gettok;   {consume the else}
  240.  
  241.       while (tok[1] <> '}') and not recovery do
  242.       begin
  243.          if (tok[1] <> '}') and (tok <> 'ELSE') then
  244.             pstatement;
  245.          usesemi;
  246.       end;
  247.    end;
  248.  
  249.    puttok;
  250.    gettok;
  251.    usesemi;
  252. end;
  253.  
  254.  
  255. (********************************************************************)
  256. procedure pif;
  257. var
  258.    pspace: integer;
  259. begin
  260.    if debug_parse then write(' <if>');
  261.  
  262.    gettok;   {consume the IF}
  263.  
  264.    pspace := length(spaces);
  265.    nospace := true;
  266.    puts('if ('+ pexpr+ ') ');
  267.    nospace := false;
  268.    
  269.    gettok;   {consume the THEN}
  270.  
  271.    if (tok[1] <> '}') and (tok <> 'ELSE') then
  272.       pstatement;
  273.  
  274.    if tok = 'ELSE' then
  275.    begin
  276.       spaces := copy(spaces,1,pspace);
  277.       if not linestart then
  278.          newline;
  279.       puts('else ');
  280.  
  281.       gettok;
  282.       if tok[1] <> '}' then
  283.          pstatement;
  284.    end;
  285.  
  286. end;
  287.  
  288.  
  289. (********************************************************************)
  290. procedure pexit;
  291. begin
  292.    if debug_parse then write(' <exit>');
  293.  
  294.    puts('return;');
  295.  
  296.    gettok;
  297.    usesemi;
  298. end;
  299.  
  300.  
  301. (********************************************************************)
  302. procedure pgoto;
  303. var
  304.    ex:  anystring;
  305.  
  306. begin
  307.    gettok;                      {consume the goto}
  308.  
  309.    if toktype = number then
  310.       ltok := 'label_' + ltok;  {modify numeric labels}
  311.  
  312.    puts('goto '+ltok+';');
  313.  
  314.    gettok;                      {consume the label}
  315.    usesemi;
  316. end;
  317.  
  318.  
  319. (********************************************************************)
  320. procedure phalt;
  321. var
  322.    ex: anystring;
  323.  
  324. begin
  325.    if debug_parse then write(' <halt>');
  326.  
  327.    gettok;
  328.  
  329.    if tok[1] = '(' then
  330.    begin
  331.       gettok;
  332.       ex := pexpr;
  333.       gettok;
  334.    end
  335.    else
  336.       ex := '0';     {default exit expression}
  337.  
  338.    puts('exit('+ex+');');
  339.  
  340.    usesemi;
  341. end;
  342.  
  343.  
  344. (********************************************************************)
  345. procedure pread;
  346. var
  347.    ctl:  string;
  348.    func: anystring;
  349.    ex:   paramlist;
  350.    p:    string;
  351.    ln:   boolean;
  352.    ty:   string[2];
  353.    i:    integer;
  354.  
  355. begin
  356.    if debug_parse then write(' <read>');
  357.    
  358.    nospace := true;   {don't copy source whitespace to output during
  359.                        this processing.  this prevents spaces from
  360.                        getting moved around}
  361.  
  362.    ln := tok = 'READLN';
  363.    nospace := true;
  364.    func := 'scanf(';
  365.  
  366.    gettok;   {consume the read}
  367.  
  368.    if tok[1] = '(' then
  369.    begin
  370.       gettok;
  371.  
  372.       if ltok[1] = '[' then   {check for MT+ [addr(name)], form}
  373.       begin
  374.          gettok;   {consume the '[' }
  375.  
  376.          if tok[1] = ']' then
  377.             func := 'scanf('
  378.          else
  379.  
  380.          begin
  381.             gettok;   {consume the ADDR}
  382.             gettok;   {consume the '(' }
  383.             func := 'tiscanf(' + usetok + ',';
  384.             gettok;   {consume the ')'}
  385.          end;
  386.  
  387.          gettok;   {consume the ']'}
  388.          if tok[1] = ',' then
  389.             gettok;
  390.       end;
  391.  
  392.       ctl := '';
  393.       ex.n := 0;
  394.  
  395.       while (tok[1] <> ')') and not recovery do
  396.       begin
  397.          p := pexpr;
  398.          ty := exprtype;
  399.  
  400.          {convert to fprintf if first param is a file variable}
  401.          if (ex.n = 0) and (ty = '@') then
  402.          begin
  403.             make_pointer(p);
  404.             func := 'tscanf(' + p + ',';
  405.          end
  406.          else
  407.  
  408.          {process a new expression; add expressions to ex.id table
  409.           and append proper control codes to the control string}
  410.          begin
  411.             if ty <> 's' then
  412.                if p[1] = '*' then
  413.                   delete(p,1,1)
  414.                else
  415.                   p := '&' + p;
  416.             inc(ex.n);
  417.             if ex.n > maxparam then
  418.                fatal('Too many params (pread)');
  419.             ex.id[ex.n] := p;
  420.             ctl := ctl + '%'+ty;
  421.          end;
  422.  
  423.          if tok[1] = ',' then
  424.             gettok;
  425.       end;
  426.  
  427.       gettok;   {consume the )}
  428.  
  429.       if ctl = '%s' then
  430.          ctl := '#';
  431.       if ln then
  432.          ctl := ctl + '\n';
  433.  
  434.       if func[1] <> 't' then
  435.          func := 't' + func + '&input,';
  436.  
  437.       puts(func+'"'+ctl+'"');
  438.       for i := 1 to ex.n do
  439.          puts(','+ex.id[i]);
  440.  
  441.       puts(')');
  442.    end
  443.  
  444.    else   {otherwise there is no param list}
  445.       if ln then
  446.          puts('scanf("\n")');
  447.  
  448.    nospace := false;
  449.    forcesemi;
  450. end;
  451.  
  452.  
  453. (********************************************************************)
  454. type
  455.    write_modes = (m_write, m_writeln, m_str);
  456.  
  457. procedure pwrite(mode: write_modes);
  458. var
  459.    ctl:  string;
  460.    func: anystring;
  461.    ex:   paramlist;
  462.    p:    string;
  463.    ty:   string[2];
  464.    i:    integer;
  465.  
  466.    procedure addform(f: anystring);
  467.       {add a form parameter, special handling for form expressions}
  468.    begin
  469.       if isnumber(f) then
  470.          ctl := ctl + f      {pass literal form}
  471.       else
  472.  
  473.       begin                      {insert form expression in parlist}
  474.          ctl := ctl + '*';
  475.          inc(ex.n);
  476.          if ex.n > maxparam then
  477.             fatal('Too many params (pwrite.form)');
  478.          ex.id[ex.n] := ex.id[ex.n-1];
  479.          ex.id[ex.n-1] := f;
  480.       end;
  481.    end;
  482.    
  483. begin
  484.    if debug_parse then write(' <write>');
  485.    
  486.    nospace := true;   {don't copy source whitespace to output during
  487.                        this processing.  this prevents spaces from
  488.                        getting moved around}
  489.  
  490.    nospace := true;
  491.  
  492.    if mode = m_str then
  493.       func := 'sbld('
  494.    else
  495.       func := 'printf(';
  496.       
  497.    gettok;   {consume the write}
  498.    
  499.    if tok[1] = '(' then
  500.    begin
  501.       gettok;   {consume the (}
  502.  
  503.       if ltok[1] = '[' then   {check for MT+ [addr(name)], form}
  504.       begin
  505.          gettok;   {consume the '[' }
  506.  
  507.          if tok[1] <> ']' then
  508.          begin
  509.             gettok;   {consume the ADDR}
  510.             gettok;   {consume the '(' }
  511.             func := 'tiprintf(' + usetok + ',';
  512.             gettok;   {consume the ')'}
  513.          end;
  514.  
  515.          gettok;   {consume the ']'}
  516.          if tok[1] = ',' then
  517.             gettok;
  518.       end;
  519.  
  520.       ctl := '';
  521.       ex.n := 0;
  522.  
  523.       while (tok[1] <> ')') and not recovery do
  524.       begin
  525.          p := pexpr;
  526.          ty := exprtype;
  527.  
  528.          {convert to fprintf if first param is a file variable}
  529.          if (ex.n = 0) and (ty = '@') then
  530.          begin
  531.             make_pointer(p);
  532.             func := 'tprintf(' + p + ',';
  533.          end
  534.          else
  535.  
  536.          {process a new expression; add expressions to ex.id table
  537.           and append proper control codes to the control string}
  538.          begin
  539.             inc(ex.n);
  540.             if ex.n > maxparam then
  541.                fatal('Too many params (pwrite)');
  542.             ex.id[ex.n] := p;
  543.  
  544.             if ty = 'D' then
  545.                ty := 'ld';
  546.             if ty = 'b' then
  547.                ty := 'd';
  548.  
  549.             {decode optional form parameters}
  550.             if tok[1] = ':' then
  551.             begin
  552.                ctl := ctl + '%';
  553.                cexprsym := voidsym; {prevent implicit conversions}
  554.                gettok;
  555.                addform(pexpr);               
  556.                
  557.                if tok[1] = ':' then
  558.                begin
  559.                   ctl := ctl + '.';
  560.                   gettok;
  561.                   addform(pexpr);
  562.                   ty := 'f';
  563.                end;
  564.                
  565.                ctl := ctl + ty;
  566.             end
  567.             else
  568.  
  569.             begin
  570.                {pass literals into the control string}
  571.                   {note: need to add escape conversions and % doubling}
  572.                if (p[1] = '"') or (p[1] = '''') then
  573.                begin
  574.                   ctl := ctl + copy(p,2,length(p)-2);
  575.                   dec(ex.n);
  576.                end
  577.  
  578.                {otherwise put in the control string for this param}
  579.                else
  580.                   ctl := ctl + '%'+ty;
  581.             end;
  582.          end;
  583.  
  584.          if tok[1] = ',' then
  585.             gettok;
  586.       end;
  587.  
  588.       gettok;   {consume the )}
  589.  
  590.       {add newline in 'writeln' translation}
  591.       if mode = m_writeln then
  592.          ctl := ctl + '\n';
  593.  
  594.       {convert last parameter into destination in 'str' translation}
  595.       if mode = m_str then
  596.       begin
  597.          func := func + ex.id[ex.n] + ',';
  598.          dec(ex.n);
  599.          delete(ctl,length(ctl)-1,2);
  600.       end;
  601.  
  602.       {produce the translated statement}
  603.       puts(func+'"'+ctl+'"');
  604.       for i := 1 to ex.n do
  605.          puts(','+ex.id[i]);
  606.  
  607.       puts(')');
  608.    end
  609.  
  610.    else   {otherwise there is no param list}
  611.       if mode = m_writeln then
  612.          puts('printf("\n")');
  613.  
  614.    nospace := false;
  615.    forcesemi;
  616. end;
  617.  
  618.  
  619. (********************************************************************)
  620. procedure pnew;
  621. var
  622.    lv:   string;
  623.    ty:   string80;
  624.  
  625. begin
  626.    if debug_parse then write(' <new>');
  627.  
  628.    gettok;   {consume the new}
  629.    gettok;   {consume the (}
  630.  
  631.    lv := plvalue;
  632.    ty := exprtype_id;
  633.    if cexprsym^.symtype = ss_pointer then
  634.       ty := ty + ' *';
  635.  
  636.    puts(lv+' = ('+ty+') malloc(sizeof(*'+lv+'));');
  637.  
  638.    gettok;   {consume the )}
  639.    usesemi;
  640. end;
  641.  
  642.  
  643. (********************************************************************)
  644. procedure pport(kw: string);
  645.    {translate port/portw/mem/memw}
  646. var
  647.    lv: string;
  648.  
  649. begin
  650.    if debug_parse then write(' <port>');
  651.  
  652.    lv := kw + '(';
  653.  
  654.    gettok;     {consume the keyword}
  655.    gettok;     {consume the [ }
  656.  
  657.    repeat
  658.       lv := lv + pexpr;
  659.       if tok[1] = ':' then
  660.       begin
  661.          gettok;
  662.          lv := lv + ',';
  663.       end;
  664.    until (tok[1] = ']') or recovery;
  665.  
  666.    gettok;     {consume the ] }
  667.  
  668.    if tok = ':=' then
  669.    begin
  670.       gettok;       {consume :=, assignment statement}
  671.       lv := lv + ',' + pexpr;
  672.    end;
  673.  
  674.    puts(lv+');');
  675.    usesemi;
  676. end;
  677.  
  678.  
  679. (********************************************************************)
  680. procedure pinline;
  681.    {translate inline statements}
  682.  
  683. var
  684.    sixteen: boolean;
  685.  
  686. begin
  687.    if debug_parse then write(' <inline>');
  688.  
  689.    gettok;     {consume the keyword}
  690.    nospace := true;
  691.    gettok;
  692.  
  693.    while (tok[1] <> ')') and not recovery do
  694.    begin
  695.       if tok[1] = '/' then
  696.          gettok;
  697.  
  698.       if tok[1] = '>' then
  699.       begin
  700.          gettok;
  701.          sixteen := true;
  702.       end
  703.       else
  704.          sixteen := htoi(ltok) > $00ff;
  705.  
  706.       putline;
  707.       if sixteen then
  708.          puts('      asm DW '+ltok+'; ')
  709.       else
  710.          puts('      asm DB '+ltok+'; ');
  711.       gettok;
  712.    end;
  713.  
  714.    nospace := false;
  715.    gettok;     {consume the ) }
  716.    usesemi;
  717. end;
  718.  
  719.  
  720. (********************************************************************)
  721. procedure pident;
  722.    {parse statements starting with an identifier;  these are either
  723.     assignment statements, function calls, return-value assignments,
  724.     or label identifiers}
  725. var
  726.    ex:   string;
  727.    lv:   string;
  728.    lvt,
  729.    ext:  char;
  730.    ety,
  731.    rty:  string;
  732.  
  733. begin
  734.    if debug_parse then write(' <ident>');
  735.  
  736.    nospace := true;   {don't copy source whitespace to output during
  737.                        this processing.  this prevents spaces from
  738.                        getting moved around}
  739.  
  740.    lv := plvalue;     {destination variable or function name}
  741.    lvt := exprtype;   {destination data type}
  742.    rty := exprtype_id;
  743.    if cexprsym^.symtype = ss_pointer then
  744.       rty := rty + ' *';
  745.  
  746.    if tok = ':=' then
  747.    begin
  748.       if debug_parse then write(' <assign>');
  749.       
  750.       gettok;       {consume :=, assignment statement}
  751.       ex := pexpr;
  752.       ext := exprtype;
  753.       ety := exprtype_id;
  754.       if cexprsym^.symtype = ss_pointer then
  755.          ety := ety + ' *';
  756.  
  757.       if iscall(lv) then      {assignment to function name}
  758.          puts('return '+ex)
  759.       else
  760.  
  761.       begin
  762. (*
  763. if debug then
  764. writeln('assign: lv{',lv,'}',lvt,' ex{',ex,'}',ext);
  765. *)
  766.          if copy(ex,1,5) = 'scat(' then
  767.             lv := 'sbld('+lv+',' + copy(ex,6,255)
  768.          else
  769.  
  770.          if lvt = 's' then
  771.          begin
  772.             if ex[1] = '''' then
  773.             begin
  774.                ex[1] := '"';
  775.                ex[length(ex)] := '"';
  776.                ext := 's';
  777.             end;
  778.  
  779.             if ext = 's' then
  780.                lv := 'strcpy('+lv+','+ex+')'
  781.             else
  782.                lv := 'sbld('+lv+',"%'+ext+'",'+ex+')';
  783.          end
  784.          else
  785.  
  786.          if lvt = 'c' then
  787.             if ext = 's' then
  788.                lv := lv+' = first('+ex+')'
  789.             else
  790.                lv := lv+' = '+ex
  791.          else
  792.  
  793.          if rty <> ety then
  794.          begin
  795.             lv := lv + ' = ' + typecast(rty, ex);
  796. (**
  797.             ltok := ex;
  798.             warning('('+ety+') casted to ('+rty+')');
  799. **)
  800.          end
  801.          else
  802.             lv := lv + ' = ' + ex;
  803.  
  804.          puts(lv);
  805.       end;
  806.    end
  807.    else
  808.  
  809.    if tok[1] = ':' then
  810.    begin
  811.       if debug_parse then write(' <label>');
  812.       
  813.       putline;
  814.       puts(lv+': ');
  815.  
  816.       gettok;       {label identifier}
  817.       usesemi;
  818.       exit;
  819.    end
  820.    else
  821.  
  822.    begin   
  823.       if debug_parse then write(' <call>');
  824.  
  825.       if not iscall(lv) then
  826.          lv := lv + '()';
  827.       puts(lv);
  828.    end;
  829.    
  830.    nospace := false;
  831.    forcesemi;
  832. end;
  833.  
  834.  
  835.  
  836.  
  837. (********************************************************************)
  838. procedure pnumlabel;
  839.    {parse statements starting with an number;  these must be
  840.     numeric labels}
  841. begin
  842.    if debug_parse then write(' <numlabel>');
  843.  
  844.    putline;
  845.    puts('label_'+tok+': ');
  846.  
  847.    gettok;      {consume the number}
  848.    gettok;      {consume the :}
  849. end;
  850.  
  851.  
  852. (********************************************************************)
  853. procedure plabel;
  854.    {parse (and throw away) a label section}
  855. begin
  856.    if debug_parse then write(' <label>');
  857.  
  858.    while tok[1] <> ';' do
  859.       gettok;
  860.  
  861.    gettok;
  862. end;
  863.  
  864.  
  865.  
  866.  
  867. (********************************************************************)
  868. (*
  869.  * process single statement
  870.  *
  871.  * expects tok to be first token of statement
  872.  * processes nested blocks
  873.  * exits with tok as end of statement
  874.  *
  875.  *)
  876.  
  877. procedure pstatement;
  878. var
  879.    builtin: boolean;
  880.    
  881. begin
  882.  
  883.    if recovery then
  884.    begin
  885.       while tok[1] <> ';' do
  886.          gettok;
  887.       gettok;
  888.       recovery := false;
  889.       exit;
  890.    end;
  891.    
  892.    if (toktype = identifier) and (cursym <> nil) then
  893.       builtin := cursym^.symtype = ss_builtin
  894.    else
  895.       builtin := false;
  896.  
  897.    if debug_parse then write(' <stmt>');
  898.  
  899.    if toktype = number then
  900.       pnumlabel
  901.    else
  902.    
  903.    case tok[1] of
  904.    '.':
  905.       exit;
  906.  
  907.    ';':
  908.       begin
  909.          puts('; ');
  910.          gettok;
  911.       end;
  912.       
  913.    '{':
  914.       pblock;
  915.  
  916.    'C':
  917.       if tok = 'CASE' then
  918.          pcase
  919.       else
  920.          pident;
  921.  
  922.    'E':
  923.       if builtin and (tok = 'EXIT') then
  924.          pexit
  925.       else
  926.          pident;
  927.  
  928.    'F':
  929.       if tok = 'FOR' then
  930.          pfor
  931.       else
  932.          pident;
  933.       
  934.    'G':
  935.       if tok = 'GOTO' then
  936.          pgoto
  937.       else
  938.          pident;
  939.          
  940.    'H':
  941.       if tok = 'HALT' then
  942.          phalt
  943.       else
  944.          pident;
  945.          
  946.    'I':
  947.       if tok = 'IF' then
  948.          pif
  949.       else
  950.       if tok = 'INLINE' then
  951.          pinline
  952.       else
  953.          pident;
  954.          
  955.    'M':
  956.       if builtin and (tok = 'MEM') then
  957.          pport('pokeb')
  958.       else
  959.       if builtin and (tok = 'MEMW') then
  960.          pport('poke')
  961.       else
  962.          pident;
  963.          
  964.    'N':
  965.       if tok = 'NEW' then
  966.          pnew
  967.       else
  968.          pident;
  969.          
  970.    'P':
  971.       if builtin and (tok = 'PORT') then
  972.          pport('outportb')
  973.       else
  974.       if builtin and (tok = 'PORTW') then
  975.          pport('outport')
  976.       else
  977.          pident;
  978.          
  979.    'R':
  980.       if tok = 'REPEAT' then
  981.          prepeat
  982.       else
  983.       if tok = 'READ' then
  984.          pread
  985.       else
  986.       if tok = 'READLN' then
  987.          pread
  988.       else
  989.          pident;
  990.  
  991.    'S':
  992.       if builtin and (tok = 'STR') then
  993.          pwrite(m_str)
  994.       else
  995.          pident;
  996.                   
  997.    'W':
  998.       if tok = 'WHILE' then
  999.          pwhile
  1000.       else
  1001.       if tok = 'WITH' then
  1002.          pwith
  1003.       else
  1004.       if tok = 'WRITE' then
  1005.          pwrite(m_write)
  1006.       else
  1007.       if tok = 'WRITELN' then
  1008.          pwrite(m_writeln)
  1009.       else
  1010.          pident;
  1011.    else
  1012.       pident;
  1013.    end;
  1014. end;
  1015.  
  1016.  
  1017. (********************************************************************)
  1018. (*
  1019.  * process begin...end blocks
  1020.  *
  1021.  * expects tok to be begin
  1022.  * exits with tok = end
  1023.  *
  1024.  *)
  1025.  
  1026. procedure pblock;
  1027. begin
  1028.    if debug_parse then write(' <block>');
  1029.  
  1030.    puts('{ ');
  1031.    gettok;                 {get first token of first statement}
  1032.  
  1033.    while (tok[1] <> '}') and not recovery do
  1034.    begin
  1035.       pstatement;          {process the statement}
  1036.       psemi;
  1037.    end;
  1038.  
  1039.    if not linestart then
  1040.       newline;
  1041.       
  1042.    puttok;                 {put the closing brace}
  1043.    gettok;
  1044.    usesemi;
  1045. end;
  1046.  
  1047.  
  1048.